package com.netease.contract.service;

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.FileNotFoundException;
import java.io.InputStream;


@Slf4j
public class SftpUploader {

	
	private String userName;
	private String password;
	
	private String host;
	private int port;

	
	public void setUserName(String userName) {
		this.userName = userName;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setHost(String host) {
		this.host = host;
	}
	
	public void setPort(int port){
		this.port=port;
	}
	
	
	private ChannelSftp channelSftp;
	
	/**
	 * 连接SFTP服务器
	 * @throws JSchException
	 * @throws SftpException
	 */
	public void connect() throws Exception {
		log.info(("--> start connect [" + this.host + ":" + this.port + "]"));
		JSch jsch = new JSch();
		Session session = jsch.getSession(userName, host, port);
		session.setPassword(password);
		session.setConfig("StrictHostKeyChecking", "no");
		session.connect(60000);
		session.sendKeepAliveMsg();
		Channel channel = session.openChannel("sftp");
		channel.connect(60000);
		channelSftp = (ChannelSftp) channel;
		log.info("--> connect OK");
		
	}
	
	public boolean isDirExist(String directory) throws SftpException {
		boolean isDirExistFlag = false;
		try {
			SftpATTRS sftpATTRS = channelSftp.lstat(directory);
			isDirExistFlag = true;
			return sftpATTRS.isDir();
		} catch (Exception e) {
			if (e.getMessage().toLowerCase().equals("no such file")) {
				isDirExistFlag = false;
			}
		}
		return isDirExistFlag;
	}
	
	public void createDir(String sftpDirPath) throws SftpException {
		
		if (isDirExist(sftpDirPath)) {
			return ;
		} else {
			// 建立目录
			channelSftp.mkdir(sftpDirPath);
			// 进入并设置为当前目录
			channelSftp.cd(sftpDirPath);
		}
	}

	/**
	 *  创建多级目录
	 * @param sftpDirPath 路径名 如 /recon/payments
	 * @throws SftpException
	 */
	public void createDirs(String sftpDirPath) throws SftpException {

		if (isDirExist(sftpDirPath)) {
			return ;
		} else {
			String paths[] = sftpDirPath.split("/");
			String remotePath = "/";
			channelSftp.cd(remotePath);
			for(String path : paths){//
				if(!StringUtils.isEmpty(path)){
					remotePath = remotePath + path + "/";
					if (isDirExist(remotePath)){
						channelSftp.cd(remotePath);
						continue;
					}
					channelSftp.mkdir(path);
					channelSftp.cd(remotePath);
				}
			}
		}
	}
	
	/**
	 * 备份文件
	 * @throws SftpException
	 */
	private void backup() throws SftpException{
		//TODO 使用NOS备份
	}
	
	/**
	 * 回滚文件
	 * @throws SftpException
	 */
	private void rollback() throws SftpException{
		//TODO
	}
	
	/**
	 * 上传文件
	 * @throws FileNotFoundException
	 * @throws SftpException
	 */
	public void deploy(String src,String dst) throws FileNotFoundException, SftpException{
		log.info(" --> start upload");
		channelSftp.put(src, dst, ChannelSftp.OVERWRITE);
		log.info(" --> upload ok:{}",dst);
	}
	
	public void deploy(InputStream src,String dst) throws FileNotFoundException, SftpException{
		log.info(" --> start upload");
		channelSftp.put(src, dst, ChannelSftp.OVERWRITE);
		log.info(" --> upload ok:{}",dst);
	}
	
	/**
	 * 退出本次SFTP
	 * @throws JSchException
	 */
	public void close() throws JSchException{
		if (this.channelSftp!=null && this.channelSftp.isConnected()){
			this.channelSftp.quit();
			this.channelSftp.exit();
			this.channelSftp.disconnect();
			channelSftp.getSession().disconnect();
		}
	}
	
	public void upload(InputStream src,String dst) throws Exception {
		try{
			this.connect();
			this.backup();
			this.deploy( src, dst);
		}catch(Exception e){
			log.error("",e);
			this.rollback();
			throw e;
		}finally{
			this.close();
		}
	}

	/**
	 *  连贯前面的动作， 完成一次文件上传。这是对外的接口方法
	 * @throws SftpException
	 * @throws JSchException
	 */
	public void upload(String src,String dst) throws Exception {
		try{
			this.connect();
			this.backup();
			this.deploy( src, dst);
		}catch(Exception e){
			log.error("",e);
			this.rollback();
			throw e;
		}finally{
			this.close();
		}
	}
}
